package com.xiaofeng.auth.domain.redis;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * @Author: chc
 * @Date: 2024/02/08/20:15
 * @Description: Redis配置类（序列化重写）
 */
@Configuration
public class RedisConfig {


    /**
     * RedisTemplate默认使用的是JdkSerializationRedisSerializer，
     * StringRedisTemplate默认使用的是StringRedisSerializer。
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        //使用StringRedisSerializer做key的序列化时，StringRedisSerializer的泛型指定的是String
        /**
         * 注意
         * 1。RedisTemplate的key指定成StringRedisSerializer序列化会报类型转换错误，如XXX类不能转换成String。
         * 2.使用Jackson2JsonRedisSerializer序列化的时候,如果实体类上没有set方法反序列化会报错。
         */
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        //设置连接对象
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        //设置String关键字类型序列换
        redisTemplate.setKeySerializer(redisSerializer);
        //设置hash关键字类型序列化
        redisTemplate.setHashKeySerializer(redisSerializer);
        //设置String类型值序列化
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer());
        //设置hash类型值序列化
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer());
        //返回序列换过的redisTemplate对象
        return redisTemplate;
    }

    private Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer() {
        Jackson2JsonRedisSerializer<Object> jsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        // 指定要序列化的域，field,get和set,以及修饰符范围，ANY是都有包括private和public
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 指定序列化输入的类型，类必须是非final修饰的，final修饰的类，比如String,Integer等会跑出异常
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        jsonRedisSerializer.setObjectMapper(objectMapper);
        //返回序列化过的Jackson2JsonRedisSerializer对象
        return jsonRedisSerializer;
    }
}
